
package de.justphil.tcg.tcgandroidclient.gui.cardfinder;

import java.util.List;

import android.content.Context;
import android.location.Location;
import android.widget.Toast;


import com.google.android.maps.MapController;
import com.google.android.maps.MapView;
import com.google.android.maps.MyLocationOverlay;

import de.justphil.tcg.tcgandroidclient.content.rest.RESTGeoCard;
import de.justphil.tcg.tcgandroidclient.util.TCGLog;

public class TCGMyLocationOverlay extends MyLocationOverlay {
	
	private final static int ON_FIX_ZOOM = 12;
	private final static float MIN_ACCURACY = 50f;
	private final static long INTERVAL = 10000;
	private final static float FIND_DISTANCE_M = 50f;
	private boolean accurate;
	private Context context;
	private double lastLat;
	private double lastLon;
	private long lastAccurateFix;
	private List<RESTGeoCard> cards;
	private OnCardFoundListener onCardFoundListener;
	
	public TCGMyLocationOverlay(Context context, MapView mapView, List<RESTGeoCard> cards,
			OnCardFoundListener onCardFoundListener) {
	
		super(context, mapView);
		this.context = context;
		this.cards = cards;
		this.onCardFoundListener = onCardFoundListener;
		final MapController mapController = mapView.getController();
		{
			enableCompass();
			enableMyLocation();
			runOnFirstFix(new Runnable() {
				
				public void run() {
				
					mapController.animateTo(getMyLocation(), new Runnable() {
						
						@Override
						public void run() {
						
							mapController.setZoom(ON_FIX_ZOOM);
						}
					});
				}
			});
		}
		Toast.makeText(
				context,
				"To collect cards your GPS must first aquire\n" + "an accuracy of " + MIN_ACCURACY
						+ "m!", Toast.LENGTH_LONG).show();
	}
	
	@Override
	public void onAccuracyChanged(int sensor, int accuracy) {
	
		super.onAccuracyChanged(sensor, accuracy);
		TCGLog.i(new Object[] {
				"MAP Accuracy changed. Sensor: ", sensor, ", Accuracy: ", accuracy });
	}
	
	@Override
	public synchronized void onLocationChanged(Location location) {
	
		super.onLocationChanged(location);
		float acc = location.getAccuracy();
		double lat = location.getLatitude();
		double lon = location.getLongitude();
		if (lat != lastLat || lon != lastLon) {
			long time = System.currentTimeMillis();
			if (acc <= MIN_ACCURACY) {
				handleNewAccurateLocation(location);
				lastAccurateFix = time;
				if (!accurate) {
					Toast.makeText(
							context,
							"Your GPS accuracy allows collecting cards!\n" + "(Accuracy: " + acc
									+ "m)", Toast.LENGTH_LONG).show();
				}
				accurate = true;
			}
			else {
				long interval = time - lastAccurateFix;
				if (interval >= INTERVAL && accurate) {
					Toast.makeText(
							context,
							"Your GPS accuracy is to low to collect cards!\n" + "(Accuracy: " + acc
									+ "m)", Toast.LENGTH_LONG).show();
					accurate = false;
				}
			}
			TCGLog.v(new Object[] {
					"MAP Location changed. Lat: ", location.getLatitude(), ", Lon: ",
					location.getLongitude(), ",Acc: ", acc });
			lastLat = lat;
			lastLon = lon;
		}
	}
	
	private void handleNewAccurateLocation(Location location) {
	
		float[] distance = new float[1];
		for (RESTGeoCard card : cards) {
			Location.distanceBetween(location.getLatitude(), location.getLongitude(),
					card.getLatitude(), card.getLongitude(), distance);
			if (distance[0] < FIND_DISTANCE_M) {
				onCardFoundListener.onCardFound(card, location);
				break;
			}
		}
	}
}
